/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/gfx/PolylineShape.h"
#include <memory.h>

namespace alkes {

PolylineShape::PolylineShape(uint32_t num)
: Shape(num)
{
    Polyline* lines = polylines_.initialize(num);
    if (lines)
    {
        memset(lines, 0, sizeof(Polyline) * num);
    }
}

PolylineShape::~PolylineShape()
{
    uint32_t i;
    for (i = 0; i < getArrayNum(); ++i)
    {
        deletePoints(polylines_[i]);
    }
}

const PolylineShape::Polyline& PolylineShape::getPolyline(uint32_t index)
{
    const static PolylineShape::Polyline NULL_POLYLINE = {
        NULL, 0, Color::BLACK, 0
    };

    AL_PRE_COND(validate(index), NULL_POLYLINE);

    return polylines_[index];
}

void PolylineShape::deletePoints(Polyline& polyline)
{
    if (polyline.points)
    {
        alkes_free(polyline.points);
        polyline.points = NULL;
    }
}

void PolylineShape::setPolyline(const Point2D* points, uint32_t count, const Color& color, uint8_t width)
{
    setPolyline(0, points, count, color, width);
}

void PolylineShape::setPolyline(uint32_t index, const Point2D* points, uint32_t count, const Color& color, uint8_t width)
{
    setPoints(index, points, count);
    setColor(index, color);
    setWidth(index, width);
}

void PolylineShape::setPoints(const Point2D* points, uint32_t count)
{
    setPoints(0, points, count);
}

void PolylineShape::setColor(const Color& color)
{
    setColor(0, color);
}

void PolylineShape::setWidth(uint8_t width)
{
    setWidth(0, width);
}

void PolylineShape::setPoints(uint32_t index, const Point2D* points, uint32_t count)
{
    AL_PRE_COND(validate(index) && (count == 0 || (count && points)), );

    if (count == 0 && polylines_[index].count == count)
        return ; // do nothing.

    if (polylines_[index].count < count)
    {
        if (polylines_[index].points)
        {
            alkes_free(polylines_[index].points);
        }
        polylines_[index].points = (Point2D*)alkes_malloc(sizeof(Point2D) * count);
    }

    polylines_[index].count = count;
    if (count)
    {
        memcpy(polylines_[index].points, points, sizeof(Point2D) * count);
    }
    else
    {
        if (polylines_[index].points)
        {
            alkes_free(polylines_[index].points);
            polylines_[index].points = NULL;
        }
    }
    setDirty(true);
}

void PolylineShape::setColor(uint32_t index, const Color& color)
{
    AL_PRE_COND(validate(index), );

    if (polylines_[index].color != color)
    {
        polylines_[index].color = color;
        setDirty(true);
    }
}

void PolylineShape::setWidth(uint32_t index, uint8_t width)
{
    AL_PRE_COND(validate(index), );

    if (polylines_[index].width != width)
    {
        polylines_[index].width = width;
        setDirty(true);
    }
}

}
